package com.gubatian.jui.demo;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description: 有界队列实现
 * @author: GuBaTian
 * @date: 2021/09/14
 */
public class MyQueue {
    /**
     * 队列的最大容量
     */
    private static final Integer MAX_CAPACITY = 100;
    /**
     * 用于在队列存储数据的链表
     */
    private volatile static LinkedList<String> linkedList = new LinkedList<>();

    public synchronized void offer(String element) {
        try {
            // 队列达到最大容量
            if (linkedList.size() == MAX_CAPACITY) {
                wait();
            }
            linkedList.addLast(element);
            // 唤醒消费线程消费
            notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 取出队列最前面的数据
     * @return
     */
    public synchronized String take() {
        String element = "";
        try {
            // 队列中没有数据了
            if (linkedList.size() == 0) {
                wait();
            }
            // 取出队列最前面的数据
            element = linkedList.removeFirst();
            // 唤醒全部线程用来从队列存取数据
            notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return element;
    }

    public static void main(String[] args) throws InterruptedException {
        MyQueue myQueue = new MyQueue();
        Thread[] offerThread = new Thread[2];
        AtomicInteger count = new AtomicInteger();
        for (int i = 0; i < offerThread.length; i++) {
            String threadName = "offer-thread" + i;
            offerThread[i] = new Thread(() -> {
                while (true) {
                    System.out.println(Thread.currentThread().getName() + "写入第" + (count.incrementAndGet()) + "条数据");
                    myQueue.offer(Thread.currentThread().getName() + "写入第" + (count.incrementAndGet()) + "条数据");
                }
            }, threadName);
        }
        for (Thread t : offerThread) {
            t.start();
        }

        Thread[] takeThread = new Thread[5];
        for (int i = 0; i < offerThread.length; i++) {
            String threadName = "take-thread" + i;
            takeThread[i] = new Thread(() -> {
                while (true) {
                    System.out.println(Thread.currentThread().getName() + "消费掉：" + myQueue.take());
                }
            }, threadName);
        }
        for (Thread t : takeThread) {
            t.start();
        }
    }
}
